package com.yfqy.app.security.login.jscode;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.yfqy.app.constant.GeneralConstants;
import com.yfqy.app.enums.ErrorCode;
import com.yfqy.app.exception.BusinessException;
import com.yfqy.app.util.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

public class JSCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    private static final Logger logger = LoggerFactory.getLogger(JSCodeAuthenticationFilter.class);

    public JSCodeAuthenticationFilter(AntPathRequestMatcher pathRequestMatcher,
                                      AuthenticationManager authenticationManager,
                                      AuthenticationSuccessHandler authenticationSuccessHandler,
                                      AuthenticationFailureHandler authenticationFailureHandler) {
        super(pathRequestMatcher);
        setAuthenticationManager(authenticationManager);
        setAuthenticationSuccessHandler(authenticationSuccessHandler);
        setAuthenticationFailureHandler(authenticationFailureHandler);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        logger.info("use JSCodeAuthenticationFilter");

        // 提取请求数据
        String requestJsonData = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        Map<String, Object> requestMapData = JSON.parseToMap(requestJsonData);
        String jsCode = (String) requestMapData.get("js_code");
        if (StringUtils.isBlank(jsCode)) {
            throw new BusinessException(ErrorCode.JS_CODE_PARAM_ERROR);
        }
        String regFromId = (String) requestMapData.get("regFromId");
        String phone = (String) requestMapData.get("phone");

        JSCodeAuthentication jsCodeAuthentication = new JSCodeAuthentication();
        jsCodeAuthentication.setJs_code(jsCode);
        jsCodeAuthentication.setRegFromId(Objects.nonNull(regFromId) ? Long.parseLong(regFromId) : GeneralConstants.DEFAULT_USER_ID);
        jsCodeAuthentication.setPhone(phone);
        jsCodeAuthentication.setAuthenticated(false);
        logger.info("微信小程序登录js_code={}", jsCode);
        return this.getAuthenticationManager().authenticate(jsCodeAuthentication);
    }
}
